package com.df.common.core.domain;

import com.df.common.utils.DateTimeUtil;
import lombok.*;
import org.springframework.util.StringUtils;

import java.time.LocalDate;

import static com.df.common.validator.CommonPreconditions.*;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;

/**
 * 周期查询参数类
 *
 * @author dunfeng
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder(toBuilder = true)
public class PeriodQuery {

    /**
     * 景区ID
     */
    private Long scenicId;

    // 周期类型
    private Integer type;

    // 年， yyyy
    private Integer year;

    // 月, 从1起始
    private Integer month;

    // 日, 从1起始
    private Integer day;

    // 时
    private Integer hour;

    // 分
    private Integer minute;

    // 秒
    private Integer second;

    // 查询年度范围时的低值
    private Integer lowerYear;

    // 查询年度范围时的高值
    private Integer higherYear;

    // 查询月度范围时的低值
    private Integer lowerMonth;

    // 查询月度范围时的高值
    private Integer higherMonth;

    // 查询日范围时的低值
    private Integer lowerDay;

    // 查询日范围时的高值
    private Integer higherDay;

    private String begin;

    private String end;

    public Integer getLowerYear() {
        if (nonNull(lowerYear))
            return lowerYear;

        LocalDate date = getBeginDate();

        if (isNull(date)) {
            return null;
        }

        lowerYear = date.getYear();
        return lowerYear;
    }

    public Integer getHigherYear() {
        if (nonNull(higherYear))
            return higherYear;

        LocalDate date = getEndDate();

        if (isNull(date)) {
            return null;
        }

        higherYear = date.getYear();
        return higherYear;
    }

    public Integer getLowerMonth() {
        if (nonNull(lowerMonth))
            return lowerMonth;

        LocalDate date = getBeginDate();

        if (isNull(date)) {
            return null;
        }

        lowerMonth = date.getMonthValue();
        return lowerMonth;
    }

    public Integer getHigherMonth() {
        if (nonNull(higherMonth))
            return higherMonth;

        LocalDate date = getEndDate();

        if (isNull(date)) {
            return null;
        }

        higherMonth = date.getMonthValue();
        return higherMonth;
    }

    public Integer getLowerDay() {
        if (nonNull(lowerDay))
            return lowerDay;

        LocalDate date = getBeginDate();

        if (isNull(date)) {
            return null;
        }

        lowerDay = date.getDayOfMonth();
        return lowerDay;
    }

    public Integer getHigherDay() {
        if (nonNull(higherDay))
            return higherDay;

        LocalDate date = getEndDate();

        if (isNull(date)) {
            return null;
        }

        higherDay = date.getDayOfMonth();
        return higherDay;
    }

    public LocalDate getBeginDate() {
        if (StringUtils.isEmpty(begin)) {
            return null;
        }

        return getLocalDate(begin);
    }

    public LocalDate getEndDate() {
        if (StringUtils.isEmpty(end)) {
            return null;
        }

        return getLocalDate(end);
    }

    public boolean containToday() {
        LocalDate beginDate = getBeginDate();
        LocalDate endDate = getEndDate();
        LocalDate today = LocalDate.now();
        return today.isAfter(beginDate) && today.isBefore(endDate) || today.isEqual(beginDate) || today.isEqual(endDate);
    }

    public boolean containCurMonth() {
        LocalDate beginDate = getBeginDate();
        LocalDate endDate = getEndDate().plusMonths(1);
        LocalDate beginDateForMonth = LocalDate.of(beginDate.getYear(), beginDate.getMonth(), 1);
        LocalDate endDateForMonth = LocalDate.of(endDate.getYear(), endDate.getMonth(), 1);
        LocalDate today = LocalDate.now();
        return today.isAfter(beginDateForMonth) && today.isBefore(endDateForMonth) || today.isEqual(beginDateForMonth) || today.isEqual(endDateForMonth);
    }

    public boolean containCurYear() {
        int beginYear = getBeginDate().getYear();
        int endYear = getEndDate().plusYears(1).getYear();
        int curYear = LocalDate.now().getYear();
        return curYear >= beginYear && curYear < endYear;
    }

    public Type getTypeEnum() {
        return Type.getTypeEnum(this.type);
    }

    private LocalDate getLocalDate(String s) {
        Type type = getTypeEnum();
        LocalDate localDate;
        switch (type) {
            case DAY:
                checkDate(s, "wrong date format.");
                localDate = DateTimeUtil.stringToLocalDate(s);
                break;
            case YEAR:
                checkDateYYYY(s, "wrong date format.");
                s += "-01-01";
                localDate = DateTimeUtil.stringToLocalDate(s);
                break;
            case MONTH:
                checkDateYYYYMM(s, "wrong date format.");
                s += "-01";
                localDate = DateTimeUtil.stringToLocalDate(s);
                break;
            default:
                localDate = null;
        }
        return localDate;
    }

    public enum Type {
        HOUR(0),
        DAY(1),
        MONTH(2),
        YEAR(3),
        TOTAL(4);

//        LAST_SEVEN_DAYS(0),
//        LAST_TWELVE_MONTHS(1),
//        LAST_TEN_YEARS(2),
//        TODAY(3),
//        CURRENT_MONTH(4),
//        CURRENT_YEAR(5),
//        TOTAL(6),
//        LAST_MONTH(7),
//        CORRESPONDING_MONTH_OF_LAST_YEAR(8);

        @Getter
        private int type;

        Type(int type) {
            this.type = type;
        }

        public static Type getTypeEnum(int type) {
            for (Type typeEnum : Type.values()) {
                if (type == typeEnum.type) {
                    return typeEnum;
                }
            }
            return null;
        }
    }
}
